package test.n00100;


import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class Problem00150 {
    public static void main(String[] args) {
        println(new int[]{-1, 0, 1, 2, -1, -4});
        println(new int[]{});
        println(new int[]{0});
    }

    public static void println(int[] nums) {
        Solution ss = new Solution();
        System.out.println(Arrays.asList(nums) + "," + ss.threeSum(nums));
    }

    public static class Solution {

        public static <T> Predicate<T> distinctByKey(Function<T, ?>... keyExtractors) {
            Map<List<?>, Boolean> seen = new ConcurrentHashMap<>();
            return t -> {
                List<?> keys = Arrays.stream(keyExtractors).map(ele -> ele.apply(t)).collect(Collectors.toList());
                return seen.putIfAbsent(keys, Boolean.TRUE) == null;
            };
        }

        /**
         * 给你一个包含 n 个整数的数组 nums，判断 nums 中是否存在三个元素 a，b，c ，使得 a + b + c = 0 ？请你找出所有和为 0 且不重复的三元组。
         * <p>
         * 注意：答案中不可以包含重复的三元组。
         * <p>
         * 来源：力扣（LeetCode）
         * 链接：https://leetcode.cn/problems/3sum
         * 著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
         *
         * @param nums
         * @return
         */
        public List<List<Integer>> threeSum(int[] nums) {
            Arrays.sort(nums);
            int len = nums.length;

            List<List<Integer>> list = new ArrayList<>();
            for (int i = 0; i < len - 2; i++) {
                for (int j = i + 1; j < len - 1; j++) {
                    for (int k = j + 1; k < len; k++) {
                        if (nums[i] + nums[j] + nums[k] == 0) {
                            list.add(Arrays.asList(nums[i], nums[j], nums[k]));
                        }
                    }
                }
            }

//            return list.stream()
//                    .map(ele -> ele.get(0) + "," + ele.get(1) + "," + ele.get(2))
//                    .collect(Collectors.toSet())
//                    .stream().map(ele -> {
//                        final String[] split = ele.split(",");
//                        return Arrays.stream(ele.split(",")).map(Integer::parseInt).collect(Collectors.toList());
//                    }).collect(Collectors.toList());

            return list.stream().filter(distinctByKey(ele -> ele.get(0), ele -> ele.get(1), ele -> ele.get(2))).collect(Collectors.toList());
        }
    }
}
